using System;
using System.Diagnostics.Contracts;

namespace ReactiveLang
{
    [ContractClass(typeof(INodeContract<>))]
    public interface INode<in TParent>
        where TParent : INodeParent
    {
        IDisposable Activate(TParent parent);
    }

    #region Contract for INode<TParent>

    [ContractClassFor(typeof(INode<>))]
    abstract class INodeContract<TParent> : INode<TParent>
        where TParent : INodeParent
    {
        public IDisposable Activate(TParent parent)
        {
            Contract.Requires<ArgumentNullException>(parent != null, "parent");
            Contract.Ensures(Contract.Result<IDisposable>() != null);
            throw new NotImplementedException();
        }
    }

    #endregion

    [ContractClass(typeof(INodeParentContract))]
    public interface INodeParent
    {
        void OnException(Exception exception);
    }

    #region Contract for INodeParent

    [ContractClassFor(typeof(INodeParent))]
    class INodeParentContract : INodeParent
    {
        public void OnException(Exception exception)
        {
            Contract.Requires<ArgumentNullException>(exception != null, "exception");
        }
    }

    #endregion
}